package list;
/**
 * ListaDoble.java
 * @author Jorge Lainfiesta 11142 Sección 20
 * @since 11/08/2012
 * @version 1
 * @param <E> Tipo de objetos que utiliza esta clase
 * Basado en código de Java Structures de Duan y Baily
 */

public class ListaDoble<E> extends AbstractList<E> {
    protected int count;
    protected NodoDoble<E> head;
    protected NodoDoble<E> tail;
    
    /**
     * Constructor
     * @post construye una lista vacía
     */
    public ListaDoble(){
        head = null;
        tail = null;
        count = 0;
    }
    /**
     * Agrega un elemento al inicio
     * @pre value no es null
     * @post agrega un elemento a la cabeza de la lista
     * @param value 
     */
    @Override
    public void addFirst(E value) {
        // construct a new element, making it head
        head = new NodoDoble<>(value, head, null);
        // fix tail, if necessary
        if (tail == null) tail = head;
        count++;
    }
    
    /**
     * Obtiene el valor del primer nodo
     * @return El valor del primer nodo
     */

    @Override
    public E getFirst(){
        return head.value();
    }
    
    /**
     * Elimina el primer elemento
     * @pre la lista no está vacía
     * @post elimina el primer elemento de la lista
     * @return Primer elemento de la lista
     */

    @Override
    public E removeFirst(){
        NodoDoble<E> temp = head;
        head = head.next();
        if (head == null) {
            tail = null;
        } else {
            head.setPrevious(null);
        }
        count--;
        return temp.value();
    }
    
    /**
     * Agrega un elemento al final 
     * @pre value no es null
     * @post agrega un elemento a la cola de la lista
     * @param value 
     */
    public void addLast(E value){
        // construct new element
        tail = new NodoDoble<>(value, null, tail);
        // fix up head
        if (head == null) head = tail;
        count++;
    }
    
    /**
     * Obtiene el valor del último nodo
     * @return El valor del último nodo
     */
    public E getLast(){
        return tail.value();
    }


    /**
     * Elimina el último elemento
     * @pre la lista no está vacía
     * @post elimina el último elemento de la lista
     * @return Último elemento de la lista
     */
    public E removeLast(){
        NodoDoble<E> temp = tail;
        tail = tail.previous();
        if (tail == null) {
            head = null;
        } else {
            tail.setNext(null);
        }
        count--;
        return temp.value();
    }
    
    /**
     * Retorna el tamaño de la lista
     * @return Tamaño de la lista
     */
    @Override
    public int size(){
        return count;
    }

}
